package com.bifrii.bo;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import com.bifrii.dao.ICommunityDAO;
import com.bifrii.dao.IEventDAO;
import com.bifrii.dao.ITopCommunityDAO;
import com.bifrii.dao.ITopEventDAO;
import com.bifrii.dao.IVoteDAO;
import com.bifrii.dao.JDBCCommunityDAO;
import com.bifrii.dao.JDBCEventDAO;
import com.bifrii.dao.JDBCTopCommunityDAO;
import com.bifrii.dao.JDBCTopEventDAO;
import com.bifrii.dao.JDBCVoteDAO;
import com.bifrii.dao.UIDGenerator;
import com.bifrii.transferObjects.Community;
import com.bifrii.transferObjects.Event;
import com.bifrii.transferObjects.Notification;
import com.bifrii.transferObjects.TopCommunity;
import com.bifrii.transferObjects.TopEvent;

public class MegaphoneManager {
	private static ICommunityDAO community;
	private static IEventDAO event;
	private static IVoteDAO vote;
	private static ITopCommunityDAO topCommunity;
	private static ITopEventDAO topEvent;
	private static MegaphoneManager mm;
	private static Integer top = 5;
	
	//creacion de un singleton para obtener siempre la misma instancia y evitar duplicidad
	public static synchronized MegaphoneManager getInstance(){
		if (mm==null)
			mm = new MegaphoneManager();
		return mm;
	}
	
	private MegaphoneManager(){
		community = new JDBCCommunityDAO();
		event = new JDBCEventDAO();
		vote = new JDBCVoteDAO();
		topCommunity = new JDBCTopCommunityDAO();
		topEvent = new JDBCTopEventDAO();
	}
	
	public List<Notification> processMegaphone()
	{
		
		List<Notification> notifications = new ArrayList<Notification>();
		
		//Obtenemos los tops de comunidades y eventos
		List<Community> communities = community.selectTopCommunities(top);
		List<Event> events = event.selectTopEvents(top);
		
		//Obtenemos los tops indexados de comunidades y eventos
		List<TopCommunity> indexedTopCommunities = topCommunity.selectTopCommunities(top);
		List<TopEvent> indexedTopEvents = topEvent.selectTopEvents(top);
		
		List<TopCommunity> topCommunities = new LinkedList<TopCommunity>();
		List<TopEvent> topEvents = new LinkedList<TopEvent>();
		
		//Calculamos los parametros necesarios para comparar los tops actuales con los indexados
		
		for(Community c: communities)
		{
			TopCommunity temp = new TopCommunity();
			
			//Calculamos los eventos que tiene la comunidad
			Integer numEvents = community.selectEvents(c.getIdCommunity()).size();
			//Calculamos los usuarios que tiene la comunidad
			Integer numUsers = community.selectAllUsers(c.getIdCommunity()).size();
			
			temp.setOid(UIDGenerator.getInstance().getKey());
			temp.setIdCommunity(c.getIdCommunity());
			temp.setEvents(numEvents);
			temp.setUsers(numUsers);
			
			topCommunities.add(temp);
		}
		
		for(Event e: events)
		{
			TopEvent temp = new TopEvent();
		
			//Calculamos los usuarios que tiene la comunidad
			Integer numUsers = event.selectAllUsers(e.getIdEvent()).size();
			Integer numVotes = vote.selectAll(e.getIdEvent()).size();
			
			temp.setOid(UIDGenerator.getInstance().getKey());
			temp.setIdEvent(e.getIdEvent());
			temp.setUsers(numUsers);
			temp.setVotes(numVotes);
			
			topEvents.add(temp);
		}
		
		//Ahora comparamos los tops obtenidos con el top actual guardado
		for(TopCommunity tc: topCommunities)
		{
			if(!indexedTopCommunities.contains(tc))
			{
				Notification notification = new Notification();
				notification.setType("community");
				notification.setId(tc.getIdCommunity());
				notification.setMessage("La comunidad "+community.select(tc.getIdCommunity()).getName() + " se ha hecho popular con " + tc.getEvents()+ " eventos y " + tc.getUsers() + " usuarios");
				notifications.add(notification);
				
				//añadimos la nueva comunidad en el top indexado y no se borran anteriores para mantener historial
				topCommunity.insert(tc);
			}
		}
		
		for(TopEvent te: topEvents)
		{
			if(!indexedTopEvents.contains(te))
			{
				Notification notification = new Notification();
				notification.setType("event");
				notification.setId(te.getIdEvent());
				notification.setMessage("El evento " +event.select(te.getIdEvent()).getName() + " se ha hecho popular con " + te.getUsers()+ " usuarios y " + te.getVotes() + " votos");
				notifications.add(notification);
				
				//añadimos el nuevo evento en el top indexado y no se borran anteriores para mantener historial
				topEvent.insert(te);
			}
		}
		
		
		return notifications;
	}
	
	
}
